#include "Socket.hpp"
#include "log.hpp"
#include <poll.h>
class PollSever
{
private:
    const static nfds_t _nfds = 100;

private:
    void accepter() // 接收逻辑是要将新的文件描述符添加到读文件描述符集里面
    {
        string ip;
        uint16_t port;
        int sock = Sock::Accept(_listensocket, &ip, &port);
        logMessage(NORMAL, "新连接到来，客户端ip: %s,端口: %d\n", ip.c_str(), port);
        int pos = 0;
        for (pos = 0; pos < _nfds; pos++)
        {
            if (_fds[pos].fd == -1)
                break;
        }
        if (pos == _nfds)
            close(sock);
        _fds[pos].fd = sock;
        _fds[pos].events = POLLIN;
        _fds[pos].revents = 0;
    }
    void recever(int pos) // 普通读取逻辑
    {
        char buffer[1024];
        int s = recv(_fds[pos].fd, buffer, sizeof(buffer) - 1, 0);
        if (s == 0)
        {
            logMessage(NORMAL, "客户端关闭\n");
            close(_fds[pos].fd);
            _fds[pos].fd = -1;
            _fds[pos].events = 0;
        }
        else if (s < 0)
        {
            logMessage(WARNING, "读取错误，我要关闭你了\n");
            close(_fds[pos].fd);
            _fds[pos].fd = -1;
            _fds[pos].events = 0;
        }
        else
        {
            buffer[s] = 0;
            // cout<<"echo : "<<buffer<<endl;
            logMessage(NORMAL, "cilent say: %s\n", buffer);
        }
    }

public:
    PollSever(uint16_t port)
        : _port(port), _timeout(1000)
    {
        // 初始化这个poll关心的结构体数组
        _fds = new struct pollfd[_nfds];
        for (int i = 0; i < _nfds; i++)
        {
            _fds[i].fd = -1;
            _fds[i].events = 0;
            _fds[i].revents = 0;
        }
        _listensocket = Sock::Socket();
        Sock::Bind(_listensocket, _port);
        Sock::Listen(_listensocket);
        _fds[0].fd = _listensocket;
        _fds[0].events = POLLIN;
        logMessage(DEBUG, "服务器初始化成功，开始监听\n");
    }

    void start()
    {
        while (1) // 每次进来都要重新初始化rfds
        {
            int rs = poll(_fds, _nfds, _timeout);
            switch (rs)
            {
            case 0:
                logMessage(DEBUG, "waiting for data reday···\n");
                continue;
            case -1:
                logMessage(WARNING, "poll error %d : %s\n", errno, strerror(errno));
                continue;
            default:
                SelectHandler(_fds);
                break;
            }
        }
    }
    ~PollSever()
    {
        if (_listensocket > 0)
            close(_listensocket);
    }

private:
    void SelectHandler(struct pollfd *pfds)
    {

        for (int i = 0; i < _nfds; i++)
        {
            // 首先要遍历数组看看每个fd是否被置位
            if (_fds[i].fd == -1)
                continue;
            // 走到这里说明一定是一个合法的fd，但也要继续判断到底是一个连接事件 还是普通事件
            if (_fds[i].revents & POLLIN)
            {
                if (i == 0) // 说明这个是连接事件，连接事件就要进行连接的逻辑
                    accepter();
                else // 这里之后才是普通事件
                    recever(i);
            }
        }
    }

private:
    int _listensocket;
    uint16_t _port;
    struct pollfd *_fds;
    int _timeout;
};